/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Global Trust Authority is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

use serde::{Deserialize, Serialize};
use validator::{Validate, ValidationError};

#[derive(Deserialize, Debug)]
pub struct QueryInfo {
    pub ids: Option<String>,
    pub cert_type: Option<String>,
}

#[derive(Debug, Deserialize, Clone)]
pub enum DeleteType {
    #[serde(rename = "id")]
    Id,
    #[serde(rename = "type")]
    Type,
    #[serde(rename = "all")]
    All,
}

#[derive(Debug, Deserialize)]
pub struct DeleteRequest {
    pub delete_type: Option<DeleteType>,
    pub ids: Option<Vec<String>>,
    #[serde(rename = "type")]
    pub cert_type: Option<String>,
}

#[derive(Debug, Validate, Deserialize, Serialize, Clone)]
#[validate(schema(function = "validate_cert_content"))]
pub struct AddCertRequest {
    #[validate(length(min = 1, max = 255))]
    pub name: String,
    #[validate(length(max = 512))]
    pub description: Option<String>,
    #[serde(rename = "type")]
    #[validate(length(min = 1), custom(function = "validate_cert_type"))]
    pub cert_type: Vec<String>,
    pub content: Option<String>,
    pub is_default: Option<bool>,
    #[validate(length(min = 1))]
    pub crl_content: Option<String>,
}

#[derive(Debug, Validate, Deserialize)]
pub struct UpdateCertRequest {
    #[validate(length(min = 1, max = 32))]
    pub id: String,
    #[validate(length(min = 1, max = 255))]
    pub name: Option<String>,
    #[validate(length(max = 512))]
    pub description: Option<String>,
    #[serde(rename = "type")]
    #[validate(length(min = 1), custom(function = "validate_cert_type_by_update"))]
    pub cert_type: Option<Vec<String>>,
    pub is_default: Option<bool>,
}

fn validate_cert_type(cert_type: &Vec<String>) -> Result<(), ValidationError> {
    if cert_type.is_empty() {
        return Err(ValidationError::new("cert type empty"));
    }

    // Check if CRL type is present
    let has_crl = cert_type.contains(&"crl".to_string());
    
    // If CRL type is present, it must be the only type
    if has_crl && cert_type.len() > 1 {
        return Err(ValidationError::new("crl type must be exclusive"));
    }

    for item in cert_type {
        if item.is_empty() || item.len() > 255 {
            return Err(ValidationError::new("invalid cert type length"));
        }
        match item.as_ref() {
            "refvalue" | "policy" | "tpm_boot" | "tpm_ima" | "crl" | "ascend_npu" => {},
            _ => return Err(ValidationError::new("invalid cert type")),
        }
    }
    Ok(())
}

fn validate_cert_type_by_update(cert_type: &Vec<String>) -> Result<(), ValidationError> {
    if cert_type.is_empty() {
        return Err(ValidationError::new("cert type empty"));
    }

    for item in cert_type {
        if item.is_empty() || item.len() > 255 {
            return Err(ValidationError::new("invalid cert type length"));
        }
        match item.as_ref() {
            "refvalue" | "policy" | "tpm_boot" | "tpm_ima" | "ascend_npu" => {},
            _ => return Err(ValidationError::new("invalid cert type")),
        }
    }
    Ok(())
}

impl UpdateCertRequest {
    pub fn validate_cert_update_body(&self) -> bool {
        self.cert_type.is_some() || self.name.is_some() || self.description.is_some() || self.is_default.is_some()
    }
}

fn validate_cert_content(request: &AddCertRequest) -> Result<(), ValidationError> {
    let has_crl = request.cert_type.contains(&"crl".to_string());
    
    if has_crl {
        // For CRL type, crl_content is required
        if request.crl_content.is_none() {
            return Err(ValidationError::new("crl content required"));
        }
    } else {
        // For non-CRL types, content is required
        if request.content.is_none() {
            return Err(ValidationError::new("content required"));
        }
    }
    
    Ok(())
}